﻿/*
Copyright © 2010 François Karman

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

See <license.txt> for the complete license of the software.
*/

using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Ghost.Tasks.Hg
{
    /// <summary>
    /// Base class for all the Hg MSBuild tasks.
    /// </summary>
    public abstract class AbstractHgTask : Task
    {
        /// <summary>
        /// The default timeout.
        /// </summary>
        internal const int DefaultTimeout = 0;

        /// <summary>
        /// Initializes a new instance of the AbstractHgTask class.
        /// </summary>
        protected AbstractHgTask()
        {
            this.Timeout = DefaultTimeout;
        }

        /// <summary>
        /// Gets or sets the local working copy.
        /// </summary>
        [Required]
        public string LocalPath { get; set; }

        /// <summary>
        /// Gets or sets the path of the hg.exe command.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The default value is <c>null</c> and in this case the <c>hg.exe</c>
        /// is considered part of the <c>Path</c> environment.
        /// </para>
        /// </remarks>
        public string LibraryLocation { get; set; }

        /// <summary>
        /// Gets or sets the timeout for the task in milliseconds.
        /// </summary>
        public int Timeout { get; set; }

        /// <summary>
        /// Executes the associated Mercurial command.
        /// </summary>
        /// <returns>
        /// <c>true</c> if the task successfully executed; otherwise, <c>false</c>.
        /// </returns>
        public override bool Execute()
        {
            string command = CommandBuilder.Build(this);

            using (HgProcess process = new HgProcess(this.LibraryLocation, command, this.LocalPath))
            {
                try
                {
                    process.StartAndWait(this.Timeout);
                }
                catch (HgProcessException exception)
                {
                    this.Log.LogErrorFromException(exception, false, true, null);
                    return false;
                }

                foreach (string error in process.Errors)
                {
                    this.Log.LogError(error);
                }

                this.ManageOutput(process.Outputs);
            }

            return !this.Log.HasLoggedErrors;
        }

        /// <summary>
        /// Manages the output of the execution to extract data.
        /// </summary>
        /// <param name="outputs">
        /// The lines of the process output.
        /// </param>
        /// <remarks>
        /// The default implementation of this method does nothing.
        /// </remarks>
        protected virtual void ManageOutput(ICollection<string> outputs)
        {
        }
    }
}
